package com.kedacom.emptyproject.util

import android.content.Context
import android.content.SharedPreferences
import android.content.res.Configuration
import android.content.res.Resources
import android.databinding.ViewDataBinding
import android.graphics.Bitmap
import android.graphics.BitmapFactory
import android.graphics.Canvas
import android.graphics.drawable.BitmapDrawable
import android.graphics.drawable.Drawable
import android.os.Build
import android.support.annotation.ColorRes
import android.support.annotation.DrawableRes
import android.support.annotation.Px
import android.support.v4.app.FragmentManager
import android.support.v4.app.FragmentTransaction
import android.support.v4.content.res.ResourcesCompat
import android.support.v4.view.ViewCompat
import android.support.v4.view.WindowInsetsCompat
import android.text.Layout
import android.text.StaticLayout
import android.text.TextPaint
import android.util.Base64
import android.util.TypedValue
import android.view.View
import android.view.ViewGroup
import com.kedacom.emptyproject.MainApplication
import java.text.SimpleDateFormat
import java.util.*


inline fun FragmentManager.commit(
    allowStateLoss: Boolean = false,
    body: FragmentTransaction.() -> Unit
) {
    val transaction = beginTransaction()
    transaction.body()
    if (allowStateLoss) {
        transaction.commitAllowingStateLoss()
    } else {
        transaction.commit()
    }
}


fun convertStringToIcon(output: String?): Bitmap? {
    var bitmap: Bitmap? = null
    return try {
        val bitmapArray: ByteArray
        bitmapArray = Base64.decode(output, Base64.DEFAULT)
        bitmap = BitmapFactory.decodeByteArray(
            bitmapArray, 0,
            bitmapArray.size
        )


        bitmap
    } catch (e: Exception) {
        null
    }
}

fun View.doOnApplyWindowInsets(f: (View, WindowInsetsCompat, ViewPaddingState) -> Unit) {

    val paddingState = createStateForView(this)
    ViewCompat.setOnApplyWindowInsetsListener(this) { v, insets ->
        f(v, insets, paddingState)
        insets
    }

    requestApplyInsetsWhenAttached()

}

fun View.requestApplyInsetsWhenAttached() {

    if (isAttachedToWindow) {
        requestApplyInsets()
    } else {
        addOnAttachStateChangeListener(object : View.OnAttachStateChangeListener {
            override fun onViewDetachedFromWindow(v: View?) {

            }

            override fun onViewAttachedToWindow(v: View?) {
                v?.requestApplyInsets()
            }

        })
    }

}

private fun createStateForView(view: View) = ViewPaddingState(
    view.paddingLeft,
    view.paddingTop, view.paddingRight, view.paddingBottom, view.paddingStart, view.paddingEnd
)

data class ViewPaddingState(
    val left: Int,
    val top: Int,
    val right: Int,
    val bottom: Int,
    val start: Int,
    val end: Int
)


inline fun View.updatePadding(
    @Px left: Int = paddingLeft,
    @Px top: Int = paddingTop,
    @Px right: Int = paddingRight,
    @Px bottom: Int = paddingBottom
) {
    setPadding(left, top, right, bottom)
}


inline fun View.setPadding(@Px size: Int) {
    setPadding(size, size, size, size)
}

inline fun SharedPreferences.edit(
    commit: Boolean = false,
    action: SharedPreferences.Editor.() -> Unit
) {
    val editor = edit()
    action(editor)
    if (commit) {
        editor.commit()
    } else {
        editor.apply()
    }
}

fun Context.dp2px(dp: Int) = (resources.displayMetrics.density * dp + .5f).toInt()
fun Context.px2dp(@Px px: Int) = (px / resources.displayMetrics.density + .5f).toInt()
fun Context.sp2px(sp: Int) = resources.displayMetrics.scaledDensity * sp + .5f

fun Context.screenHeight() = (resources.displayMetrics.heightPixels)
fun Context.screenWidth() = (resources.displayMetrics.widthPixels)

fun Context.statusBarHeight(): Int {
    var statusBarHeight = 0
    val resourceId: Int =
        resources.getIdentifier("status_bar_height", "dimen", "android")
    if (resourceId > 0) {
        statusBarHeight = resources.getDimensionPixelSize(resourceId)
    }
    return statusBarHeight
}

fun Context.dp2px(dp: Float): Float {
    return TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp, resources.displayMetrics)
}

fun Int.dp2px() =
    (MainApplication.applicationContext.resources.displayMetrics.density * this + .5f).toInt()

fun Float.dp2px() =
    (MainApplication.applicationContext.resources.displayMetrics.density * this + .5f).toInt()

fun View.margin(start: Int = 0, top: Int = 0, end: Int = 0, bottom: Int = 0) {

    this.layoutParams = (this.layoutParams as ViewGroup.MarginLayoutParams).apply {
        leftMargin = start
        topMargin = top
        rightMargin = end
        bottomMargin = bottom

    }

}

fun Canvas.withRotate(degrees: Float, block: Canvas.() -> Unit) {
    val checkPoint = save()
    rotate(degrees)
    try {
        block()
    } finally {
        restoreToCount(checkPoint)
    }
}

fun Drawable.toBitmap(
    @Px width: Int = intrinsicWidth,
    @Px height: Int = intrinsicHeight,
    config: Bitmap.Config? = null
): Bitmap {
    if (this is BitmapDrawable) {
        if (config == null || bitmap.config == config) {
            // Fast-path to return original. Bitmap.createScaledBitmap will do this check, but it
            // involves allocation and two jumps into native code so we perform the check ourselves.
            if (width == intrinsicWidth && height == intrinsicHeight) {
                return bitmap
            }
            return Bitmap.createScaledBitmap(bitmap, width, height, true)
        }
    }

    val oldBounds = bounds

    val bitmap = Bitmap.createBitmap(width, height, config ?: Bitmap.Config.ARGB_8888)
    setBounds(0, 0, width, height)
    draw(Canvas(bitmap))

    setBounds(oldBounds.left, oldBounds.top, oldBounds.right, oldBounds.bottom)
    return bitmap
}

/**
 * Wrap the specified [block] in calls to [Canvas.save]/[Canvas.translate]
 * and [Canvas.restoreToCount].
 */
inline fun Canvas.withTranslation(
    x: Float = 0.0f,
    y: Float = 0.0f,
    block: Canvas.() -> Unit
) {
    val checkpoint = save()
    translate(x, y)
    try {
        block()
    } finally {
        restoreToCount(checkpoint)
    }
}

/**
 * Wrap the specified [block] in calls to [Canvas.save]/[Canvas.rotate]
 * and [Canvas.restoreToCount].
 */
inline fun Canvas.withRotation(
    degrees: Float = 0.0f,
    pivotX: Float = 0.0f,
    pivotY: Float = 0.0f,
    block: Canvas.() -> Unit
) {
    val checkpoint = save()
    rotate(degrees, pivotX, pivotY)
    try {
        block()
    } finally {
        restoreToCount(checkpoint)
    }
}

fun Resources.getResColor(@ColorRes id: Int, theme: Resources.Theme? = null): Int {
    return ResourcesCompat.getColor(this, id, theme)
}

fun Resources.getResDrawable(@DrawableRes id: Int, theme: Resources.Theme? = null): Drawable? {
    return ResourcesCompat.getDrawable(this, id, theme)
}


fun newStaticLayout(
    source: CharSequence,
    paint: TextPaint,
    width: Int,
    alignment: Layout.Alignment,
    spacingMult: Float,
    spacingAdd: Float,
    includePad: Boolean
): StaticLayout {

    return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {

        StaticLayout.Builder.obtain(source, 0, source.length, paint, width).apply {
            setAlignment(alignment)
            setLineSpacing(spacingAdd, spacingMult)
            setIncludePad(includePad)
        }.build()

    } else {

        @Suppress("DEPRECATION")
        (StaticLayout(source, paint, width, alignment, spacingMult, spacingAdd, includePad))

    }

}

inline fun ViewGroup.forEach(action: (view: View) -> Unit) {
    for (index in 0 until childCount) {
        action(getChildAt(index))
    }
}

inline fun <T : ViewDataBinding> T.executeAfter(block: T.() -> Unit) {
    block()
    executePendingBindings()
}

inline fun View.doOnLayout(crossinline action: (view: View) -> Unit) {
    if (ViewCompat.isLaidOut(this) && !isLayoutRequested) {
        action(this)
    } else {
        doOnNextLayout {
            action(it)
        }
    }
}

inline fun View.doOnNextLayout(crossinline action: (view: View) -> Unit) {
    addOnLayoutChangeListener(object : View.OnLayoutChangeListener {
        override fun onLayoutChange(
            view: View,
            left: Int,
            top: Int,
            right: Int,
            bottom: Int,
            oldLeft: Int,
            oldTop: Int,
            oldRight: Int,
            oldBottom: Int
        ) {
            view.removeOnLayoutChangeListener(this)
            action(view)
        }
    })
}


fun Context.isLandscape(): Boolean {
    return resources.configuration.orientation == Configuration.ORIENTATION_LANDSCAPE
}

fun Context.isPortrait(): Boolean {
    return resources.configuration.orientation == Configuration.ORIENTATION_PORTRAIT
}

var lastTime = ""

//fun getCurDay(boolean: Boolean): String {
//    return if (boolean|| lastTime.isEmpty()) {
//        val calendar = Calendar.getInstance()
//        calendar.add(Calendar.DATE, -1) //向前走一天
//        val date = calendar.time
//        var formatter = SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
//        lastTime = formatter.format(date)
//        lastTime
//    }else{
//        lastTime
//
//    }


fun getCurDay(boolean: Boolean): String {
    return if (boolean || lastTime.isEmpty()) {
        val calendar = Calendar.getInstance()
//        calendar.add(Calendar.DATE, -1) //向前走一天
        calendar.set(Calendar.MINUTE, Calendar.MINUTE - 720); //当前分钟的前后分钟，
        val date = calendar.time
        var formatter = SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        lastTime = formatter.format(date)
        lastTime
    } else {
        lastTime
    }

}

